package com.sunwayworld.basemodule.samplemanage.samplecodegenerate.service.impl;

import com.deepoove.poi.config.ConfigureBuilder;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.sunwayworld.basemodule.basedata.exporttemplate.bean.LimsExportTemplateBean;
import com.sunwayworld.basemodule.basedata.exporttemplate.service.LimsExportTemplateService;
import com.sunwayworld.basemodule.common.utils.ExportUtil;
import com.sunwayworld.basemodule.samplemanage.sample.dto.LimsBarCodeDTO;
import com.sunwayworld.basemodule.samplemanage.sample.dto.LimsSampleTagDTO;
import com.sunwayworld.basemodule.samplemanage.samplecodegenerate.bean.LimsSamplecodeGenerateRecordBean;
import com.sunwayworld.basemodule.samplemanage.samplecodegenerate.dao.LimsSamplecodeGenerateRecordDao;
import com.sunwayworld.basemodule.samplemanage.samplecodegenerate.service.LimsSamplecodeGenerateRecordService;
import com.sunwayworld.cloud.lims.reporttemplate.service.LimsReportTemplateService;
import com.sunwayworld.framework.at.annotation.AuditTrailEntry;
import com.sunwayworld.framework.at.annotation.AuditTrailType;
import com.sunwayworld.framework.context.ApplicationContextHelper;
import com.sunwayworld.framework.exception.InvalidDataException;
import com.sunwayworld.framework.io.file.FilePathDTO;
import com.sunwayworld.framework.io.file.FilePathManager;
import com.sunwayworld.framework.io.file.FileScope;
import com.sunwayworld.framework.mybatis.mapper.MatchPattern;
import com.sunwayworld.framework.mybatis.mapper.SearchFilter;
import com.sunwayworld.framework.restful.data.RestJsonWrapperBean;
import com.sunwayworld.framework.spring.annotation.GikamBean;
import com.sunwayworld.framework.utils.EncryptUtils;
import com.sunwayworld.framework.utils.FileUtils;
import com.sunwayworld.framework.utils.StringUtils;
import com.sunwayworld.module.item.file.bean.CoreFileBean;
import com.sunwayworld.module.item.file.manager.CoreFileManager;
import com.sunwayworld.module.item.file.service.CoreFileService;
import com.sunwayworld.module.item.file.utils.CoreFileUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Repository
@GikamBean
public class LimsSamplecodeGenerateRecordServiceImpl implements LimsSamplecodeGenerateRecordService {
    private static final Logger logger = LogManager.getLogger(LimsSamplecodeGenerateRecordServiceImpl.class);

    // 二维码颜色
    private static final int BLACK = 0xFF000000;
    // 二维码颜色
    private static final int WHITE = 0xFFFFFFFF;

    @Autowired
    @Lazy
    private CoreFileManager coreFileManager;

    @Autowired
    private LimsSamplecodeGenerateRecordDao limsSamplecodeGenerateRecordDao;

    @Autowired
    @Lazy
    private CoreFileService coreFileService;

    @Autowired
    @Lazy
    private LimsExportTemplateService limsExportTemplateService;

    @Override
    @SuppressWarnings("unchecked")
    public LimsSamplecodeGenerateRecordDao getDao() {
        return limsSamplecodeGenerateRecordDao;
    }

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.INSERT)
    public Long insert(RestJsonWrapperBean jsonWrapper) {
        LimsSamplecodeGenerateRecordBean limsSamplecodeGenerateRecord = jsonWrapper.parseUnique(LimsSamplecodeGenerateRecordBean.class);
        limsSamplecodeGenerateRecord.setId(ApplicationContextHelper.getNextIdentity());
        getDao().insert(limsSamplecodeGenerateRecord);
        return limsSamplecodeGenerateRecord.getId();
    }

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.UPDATE)
    public Long print(RestJsonWrapperBean wrapper) {
        Long fileId = null;
        List<LimsSamplecodeGenerateRecordBean> samplecodeGenerateRecordBeans = wrapper.parse(LimsSamplecodeGenerateRecordBean.class);
        if (!samplecodeGenerateRecordBeans.isEmpty()) {
            // 查询标签模板
            List<LimsExportTemplateBean> limsExportTemplateBeans =
                    limsExportTemplateService.selectListByFilter(
                            SearchFilter.instance().match("templateCode", "GenerateSampleCodePrintTemplate")
                                    .filter(MatchPattern.EQ));

            if (!limsExportTemplateBeans.isEmpty()) {
                CoreFileBean template = coreFileService.selectById(limsExportTemplateBeans.get(0).getTemplateFileId());
                FilePathDTO fr = CoreFileUtils.toFilePath(template);

                String templatePath = FilePathManager.getLocalPath(fr).toString();
                logger.info("templatePath----".concat(templatePath));
                if (StringUtils.isBlank(templatePath)) {
                    throw new InvalidDataException("LIMS.BUSINESS.REPORT.ALERT.NO_TEMPLATE");
                }
                coreFileManager.download(template, FilePathManager.getLocalPath(fr));
                // 填充模板，生成文件
                try (InputStream templateFile = new FileInputStream(templatePath);
                     ByteArrayOutputStream os = new ByteArrayOutputStream()) {
                    ExportUtil.build(templateFile, builder -> this.buildSampleTagParams(builder, samplecodeGenerateRecordBeans), os);

                    // 生成的文件导入到系统
                    fileId = ApplicationContextHelper.getNextIdentity();
                    CoreFileBean insertCoreFile = new CoreFileBean();
                    insertCoreFile.setId(fileId);
                    insertCoreFile.setTargetId("T_LIMS_SAMPLE_CODE_BARCODE" + "$" + StringUtils.randomUUID());//分类报告
                    insertCoreFile.setName("样本编号标签.docx");
                    insertCoreFile.setFileExt(FileUtils.getFileExtension(insertCoreFile.getName()));
                    insertCoreFile.setMd5Name(EncryptUtils.MD5Encrypt(fileId + "$" + insertCoreFile.getName()));
                    insertCoreFile.setScope(FileScope.secure.name());
                    insertCoreFile.setSize((long) os.size());
                    insertCoreFile.setTimes(0L);
                    insertCoreFile.setExt("docx");
                    insertCoreFile.setDownloadable("1");
                    insertCoreFile.setCreatedTime(LocalDateTime.now());
                    coreFileService.getDao().insert(insertCoreFile);
                    //downloadUrl = coreFileManager.getAbsoluteDownloadUrl(insertCoreFile.getId());

                    try (ByteArrayInputStream in = new ByteArrayInputStream(os.toByteArray())) {
                        coreFileManager.upload(insertCoreFile, in);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return fileId;
    }

    /**
     * *********************************************************************************
     * 构建word需要的参数
     *
     * @param configureBuilder 构建配置
     * @return word参数
     */
    private LimsSampleTagDTO buildSampleTagParams(ConfigureBuilder configureBuilder, List<LimsSamplecodeGenerateRecordBean> samplecodeGenerateRecordBeans) {
        LimsSampleTagDTO limsSampleTagDTO = new LimsSampleTagDTO();
        String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        List<LimsBarCodeDTO> limsBarCodeDTOList = new ArrayList<>();
        for (LimsSamplecodeGenerateRecordBean generateRecordBean : samplecodeGenerateRecordBeans) {
            LimsBarCodeDTO limsBarCodeDTO = new LimsBarCodeDTO();
            limsBarCodeDTO.setSampleCode(generateRecordBean.getGenerateSampleCode());
            limsBarCodeDTO.setBarcode(zxingCodeCreate(generateRecordBean.getGenerateSampleCode(), 500, 500));
            limsBarCodeDTO.setDate(date);
            limsBarCodeDTO.setBarCodeSize(40);
            limsBarCodeDTOList.add(limsBarCodeDTO);
        }
        limsSampleTagDTO.setLimsBarCodeDTOList(limsBarCodeDTOList);
        return limsSampleTagDTO;
    }

    /**
     * 生成二维码
     *
     * @param text   二维码内容
     * @param width  二维码宽
     * @param height 二维码高
     */
    public static byte[] zxingCodeCreate(String text, int width, int height) {
        Map<EncodeHintType, String> his = new HashMap<>();
        // 设置编码字符集
        his.put(EncodeHintType.CHARACTER_SET, "utf-8");
        try {
            // 1、生成二维码
            BitMatrix encode = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height, his);

            // 2、获取二维码宽高
            int codeWidth = encode.getWidth();
            int codeHeight = encode.getHeight();

            // 3、将二维码放入缓冲流
            BufferedImage image = new BufferedImage(codeWidth, codeHeight, BufferedImage.TYPE_INT_RGB);
            for (int i = 0; i < codeWidth; i++) {
                for (int j = 0; j < codeHeight; j++) {
                    // 4、循环将二维码内容定入图片
                    image.setRGB(i, j, encode.get(i, j) ? BLACK : WHITE);
                }
            }
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ImageIO.write(image, "jpg", out);
            return out.toByteArray();
        } catch (WriterException e) {
            e.printStackTrace();
            System.out.println("二维码生成失败");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("生成二维码图片失败");
        }
        return null;
    }
}
